﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;

namespace System.Windows.Media.Media3D10
{
    /// <summary>
    /// Représente un <see cref="GeneralTransform3D10"/> qui est un composite des transformations dans son <see cref="GeneralTransform3D10Collection"/>.
    /// </summary>
    [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
    [ContentProperty("Children")]
    public sealed class GeneralTransform3D10Group : GeneralTransform3D10
    {
        #region Dependency Properties
        /// <summary>
        /// Identifie la propriété de dépendance <see cref="Children"/>.
        /// </summary>
        public static readonly DependencyProperty ChildrenProperty =
            DependencyProperty.Register("Children", typeof(GeneralTransform3D10Collection), typeof(GeneralTransform3D10Group),
            new PropertyMetadata(new PropertyChangedCallback(Children_PropertyChanged)));
        #endregion

        #region Dependency Properties Callbacks
        private static void Children_PropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (object.ReferenceEquals(sender, null))
                throw new ArgumentNullException("sender");
            if (object.ReferenceEquals(e, null))
                throw new ArgumentNullException("e");
            (sender as GeneralTransform3D10Group).OnChildrenChanged(e);
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Initialise une nouvelle instance de la classe <see cref="GeneralTransform3D10Group"/>
        /// </summary>
        public GeneralTransform3D10Group()
        {
            this.Children = new GeneralTransform3D10Collection();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Obtient ou définit la collection d'objets <see cref="GeneralTransform3D10"/> qui constituent ce <see cref="GeneralTransform3D10Group"/>. 
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227")]
        public GeneralTransform3D10Collection Children
        {
            get { return (GeneralTransform3D10Collection)GetValue(ChildrenProperty); }
            set { SetValue(ChildrenProperty, value); }
        }
        
        /// <summary>
        /// Obtient la transformation inverse de ce <see cref="GeneralTransform3D10Group"/>, s'il comporte un univers.
        /// </summary>
        public override GeneralTransform3D10 Inverse
        {
            get { return null; }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Crée un clone modifiable de ce <see cref="GeneralTransform3D10Group"/>, en créant des copies complètes des valeurs de cet objet.
        /// Lors de la copie de propriétés de dépendance, cette méthode copie les références de ressources et les liaisons de données (même si elles ne peuvent plus être résolues), mais pas les animations ni leurs valeurs actuelles.
        /// </summary>
        /// <returns>
        /// Clone modifiable de l'objet actuel.
        /// La valeur de la propriété <see cref="Freezable.IsFrozen"/> de l'objet cloné est false, même si la valeur de la propriété <see cref="Freezable.IsFrozen"/> de la source est true.
        /// </returns>
        public new GeneralTransform3D10Group Clone()
        {
            return base.Clone() as GeneralTransform3D10Group;
        }

        /// <summary>
        /// Crée un clone modifiable de ce <see cref="GeneralTransform3D10Group"/>, en créant des copies complètes des valeurs actuelles de cet objet.
        /// Contrairement à leurs valeurs actuelles, les références de ressources, les liaisons de données et les animations ne sont pas copiées.
        /// </summary>
        /// <returns>
        /// Clone modifiable de l'objet actuel.
        /// La valeur de la propriété <see cref="Freezable.IsFrozen"/> de l'objet cloné est false, même si la valeur de la propriété <see cref="Freezable.IsFrozen"/> de la source est true.
        /// </returns>
        public new GeneralTransform3D10Group CloneCurrentValue()
        {
            return base.CloneCurrentValue() as GeneralTransform3D10Group;
        }
        #endregion

        #region Private Methods
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822")]
        private void OnChildrenChanged(DependencyPropertyChangedEventArgs e)
        {
            if (object.ReferenceEquals(e, null))
                throw new ArgumentNullException("e");
        }
        #endregion

        #region GeneralTransform3D10 Implementation
        /// <summary>
        /// Tente de transformer le vecteur spécifié.
        /// </summary>
        /// <param name="inVector">Vecteur à transformer.</param>
        /// <param name="result">Résultat de la transformation de <paramref name="inVector"/>.</param>
        /// <returns>true si <paramref name="inVector"/> a été transformé ; sinon, false.</returns>
        public override bool TryTransform(SlimDX.Vector3 inVector, out SlimDX.Vector3 result)
        {
            result = inVector;
            for (int i = 0; i < this.Children.Count; i++)
            {
                if (!this.Children[i].TryTransform(result, out result))
                {
                    result = SlimDX.Vector3.Zero;
                    return false;
                }
            }
            return true;
        }
        #endregion

        #region Freezable Implementation
        /// <summary>
        /// Une fois implémentée dans une classe dérivée, initialise une nouvelle instance de la classe dérivée <see cref="Freezable"/>. 
        /// </summary>
        /// <returns>Nouvelle instance.</returns>
        protected override Freezable CreateInstanceCore()
        {
            return new GeneralTransform3D10Group();
        }
        #endregion
    }
}
